/*
 * Copyright (c) 2025, 大连理工大学 (Dalian University of Technology)
 *
 * Licensed under the Mulan PSL v2.
 * You can use this file according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of the License at
 *
 *     http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. SEE THE MULAN PSL v2
 * FOR MORE DETAILS.
 */

/**
 * @brief   : 提供的数据存储接口
 * @version : 0.1
 * @author  : 武兴创
 * @date    : 2024.10.21
 */
#pragma once

#include "Utility/Algebra/Matrix.h"

#include "DataStructure/Input/Element/CBARData.h"
#include "DataStructure/Input/Element/CBEAMData.h"
#include "DataStructure/Input/Element/CBUSHData.h"
#include "DataStructure/Input/Element/CDAMP1Data.h"
#include "DataStructure/Input/Element/CDAMP2Data.h"
#include "DataStructure/Input/Element/CDAMP3Data.h"
#include "DataStructure/Input/Element/CDAMP4Data.h"
#include "DataStructure/Input/Element/CELAS1Data.h"
#include "DataStructure/Input/Element/CELAS2Data.h"
#include "DataStructure/Input/Element/CELAS3Data.h"
#include "DataStructure/Input/Element/CELAS4Data.h"
#include "DataStructure/Input/Element/CFASTData.h"
#include "DataStructure/Input/Element/CHBDYGData.h"
#include "DataStructure/Input/Element/CHBDYPData.h"
#include "DataStructure/Input/Element/CHEXAData.h"
#include "DataStructure/Input/Element/CMASS1Data.h"
#include "DataStructure/Input/Element/CMASS2Data.h"
#include "DataStructure/Input/Element/CMASS3Data.h"
#include "DataStructure/Input/Element/CMASS4Data.h"
#include "DataStructure/Input/Element/CONM1Data.h"
#include "DataStructure/Input/Element/CONM2Data.h"
#include "DataStructure/Input/Element/CONRODData.h"
#include "DataStructure/Input/Element/CPENTAData.h"
#include "DataStructure/Input/Element/CPYRAMData.h"
#include "DataStructure/Input/Element/CQUAD4Data.h"
#include "DataStructure/Input/Element/CQUADRData.h"
#include "DataStructure/Input/Element/CRODData.h"
#include "DataStructure/Input/Element/CSHEARData.h"
#include "DataStructure/Input/Element/CTETRAData.h"
#include "DataStructure/Input/Element/CTRIA3Data.h"
#include "DataStructure/Input/Element/CTRIA6Data.h"
#include "DataStructure/Input/Element/CVISCData.h"
#include "DataStructure/Input/Element/CWELDData.h"
#include "DataStructure/Input/Element/ElementTypes.h"

#include "DBManager/DBServiceFactory.h"

class IElementSummaryRepository;

SG_DBMANAGER_NAMESPACE_OPEN

class DBManager_DECLSPEC IElementService
{
  public:
    virtual ~IElementService ();

    IElementService (SG::DBManager::DBServiceFactory* dbServiceFactory);

    /** @brief 模型中包含的单元类型
     *
     * 此处不包含所有的R单元
     */
    std::vector<SG::DataStructure::FEM::ElementTypes> GetAllElementTypes ();

    /**
     * @brief   : Get the Element Type By Id
     * @param   : eid
     * @return  :
     * @author  : wxc
     * @date    : 2024.10.21
     */
    SG::DataStructure::FEM::ElementTypes GetElementType (SG::DataStructure::Common::Id eid);

    /**
     * @brief   :  类型为`type`的单元的数量
     * @param   : type
     * @return  :
     * @author  : wxc
     * @date    : 2024.10.21
     */
    std::size_t GetElementSize (SG::DataStructure::FEM::ElementTypes type);

    /**
     * @brief   : 获取指定类型的所有单元ID
     * @param   : type 单元类型
     * @return  : 指定类型的所有单元ID列表
     * @author  : wuxingchuang
     * @date    : 2025.07.25
     */
    std::vector<SG::DataStructure::Common::Id> GetElementIdsByType (SG::DataStructure::FEM::ElementTypes type);

    /**
     * @brief    某种单元类型的所有节点， 返回矩阵行数等于单元数量，列数等于单元节点数目
     * @return
     * @author   wuxingchuang
     * @date     2025.07.31
     */
    SG::Algebra::Matrix GetElementNodes (SG::DataStructure::FEM::ElementTypes type);

    /**
     * @brief    获取某单元Id的节点列表
     *
     * @param    type
     * @return
     * @author   wuxingchuang
     * @date     2024.12.24
     */
    std::vector<SG::DataStructure::Common::Id> FindElementNodes (SG::DataStructure::Common::Id eid);

    /**
     * @brief  根据单元ID获取单元类型和Index
     *
     * @param    eleId
     * @param    etypes 未使用
     * @return   单元类型和Index
     * @author   wuxingchuang
     * @date     2025.02.06
     */
    SG::DataStructure::FEM::ElementTypes FindElement (SG::DataStructure::Common::Id                            eleId,
                                                      const std::vector<SG::DataStructure::FEM::ElementTypes>& etypes = {});

    /**
     * @brief    获取所有单元Id
     *
     * @return
     * @author   wuxingchuang
     * @date     2025.02.19
     */
    std::vector<SG::DataStructure::Common::Id> GetAllElementId ();

    /**
     * @brief    将对应ID的数据库复制至dest数据库
     *
     * @param    src
     * @param    dest
     * @param    id
     * @author   wuxingchuang
     * @date     2025.02.20
     */
    // virtual SG::DataStructure::Common::Status CopyData (DBServiceFactory* const dest, std::vector<SG::DataStructure::Common::Id> id);

    /**
     * @brief    根据nodeid查询节点id
     *
     * @param    nodeId
     * @return
     * @author   wanglong
     * @date     2025.03.13
     */
    std::vector<SG::DataStructure::Common::Id> GetElementIdByNode (SG::DataStructure::Common::Id nodeId);

    /**
     * @brief   通过单元id 查询壳截面属性id
     *
     * @author   wanghuan
     * @date     2025.04.07
     */
    SG::DataStructure::Common::Id QueryShellPropId (SG::DataStructure::Common::Id& shellId);

    /**
     * @brief    通过属性ID查找单元
     *
     * @author   wuxingchuang
     * @date     2025.07.10
     */
    std::vector<SG::DataStructure::Common::Id> FindElementByPropId (SG::DataStructure::Common::Id propId);

    template <typename TDataType>
    SG::DataStructure::Common::Status Add (TDataType& data)
    {
        return GetDataOperate ().Add<TDataType> (data);
    };

    template <typename TDataType>
    SG::DataStructure::Common::Status MultiAdd (TDataType& data)
    {
        return GetDataOperate ().MultiAdd<TDataType> (data);
    };

    template <typename TDataType>
    SG::DataStructure::Common::Status FindByIndex (std::size_t index, TDataType& _OUT entity)
    {
        return GetDataOperate ().FindByIndex<TDataType> (index, entity);
    };

    template <typename TDataType>
    SG::DataStructure::Common::Status FindById (SG::DataStructure::Common::Id id, TDataType& _OUT entity)
    {
        return GetDataOperate ().FindById<TDataType> (id, entity);
    };

    template <typename TDataType>
    std::size_t Size ()
    {
        return GetDataOperate ().Size<TDataType> ();
    };

    template <typename TDataType>
    std::vector<SG::DataStructure::Common::Id> GetAllId ()
    {
        return GetDataOperate ().GetAllId<TDataType> ();
    };

    template <typename TDataType>
    std::vector<TDataType> GetAllData ()
    {
        return GetDataOperate ().GetAllData<TDataType> ();
    };

    template <typename TDataType>
    std::size_t Count (SG::DataStructure::Common::Id id)
    {
        return GetDataOperate ().Count<TDataType> (id);
    };

  private:
    DBServiceFactory*          m_dbm        = nullptr;
    IElementSummaryRepository* m_repository = nullptr;

    DataOperate&               GetDataOperate ();
    IElementSummaryRepository* GetRepository ();
};

template <>
std::shared_ptr<IElementService> DBManager_DECLSPEC DBServiceFactory::get ();

SG_DBMANAGER_NAMESPACE_CLOSE
